package com.wxd.framework.common.mybatis;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.wxd.framework.common.Criteria;
import com.wxd.framework.common.page.Pagination;


/**
 * MyBatis 通用Dao
 * @author
 *
 */
@SuppressWarnings("unchecked" )
public class MyBatisGenericDao extends SqlSessionDaoSupport {
    
    @Autowired  
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){  
        super.setSqlSessionFactory(sqlSessionFactory);  
    }
	
	//---------------------自动
	public static final String	POSTFIX_SELECT_PRIAMARYKEY	= ".selectByPrimaryKey";
	public static final String	POSTFIX_DELETE_PRIAMARYKEY	= ".deleteByPrimaryKey";
	public static final String	POSTFIX_INSERT				= ".insert";
	public static final String	POSTFIX_INSERT_SELECTIVE	= ".insertSelective"; 
	public static final String	POSTFIX_UPDATE_SELECTIVE	= ".updateByPrimaryKeySelective";
	public static final String	POSTFIX_UPDATE	 		= ".updateByPrimaryKey";
	
	public static final String	POSTFIX_SELECT_PAGINATION_CRITERIA = ".selectPaginationByCriteria";
	
	public static final String	POSTFIX_SELECT_LIST_CRITERIA = ".selectListByCriteria";
	
	//---------------------手动
	public static final String	POSTFIX_SELECT_ALLLIST			= ".selectAllList";
	public static final String	POSTFIX_COUNT				= "_count";
	
	public static final String	POSTFIX_SELECT_LIST_MAP		= ".selectListByMap";	
	public static final String	POSTFIX_SELECT_LIST_SQL		= ".selectListBySql";
	public static final String	POSTFIX_DELETE				= ".delete";
	
	
	
	/**
	 * 根据PrimaryKey获取对象
	 */
	public <T> T selectByPrimaryKey(String namespace, Serializable id){
		Object obj = getSqlSession().selectOne(namespace + POSTFIX_SELECT_PRIAMARYKEY, id);
		if(obj != null)
		{
			return (T)obj;
		}else {
			return null;
		}
	}
		
	/**
	 * 获取全部对象
	 */
	public <T> List<T> selectAllList(String namespace){
		return getSqlSession().selectList(namespace + POSTFIX_SELECT_ALLLIST);
	}
	
	
	/**
	 * 新增对象
	 */
	public int insert(String namespace, Object obj){
		return getSqlSession().insert(namespace + POSTFIX_INSERT, obj);
	}
	
	/**
	 * 新增对象（判断属性是否为空）
	 */
	public int insertSelective(String namespace, Object obj){
		return getSqlSession().insert(namespace + POSTFIX_INSERT_SELECTIVE, obj);
	}
	
	/**
	 * 保存对象  
	 */
	public int update(String namespace, Object obj){
		return getSqlSession().update(namespace + POSTFIX_UPDATE, obj);
	}
	
	/**
	 * 保存对象（判断属性是否为空）
	 */
	public int updateSelective(String namespace, Object obj){
		return getSqlSession().update(namespace + POSTFIX_UPDATE_SELECTIVE, obj);
	}
		
	/**
	 * 根据PrimaryKey删除对象
	 */
	public int deleteByPrimaryKey(String namespace, Serializable id){
		return getSqlSession().delete(namespace + POSTFIX_DELETE_PRIAMARYKEY, id);
	}
	
	/**
	 * 根据Criteria 查询
	 * @param namespace
	 * @param criteria
	 * @return
	 */
	public <T> List<T> selectListByCriteria(String namespace, Criteria criteria){
		return getSqlSession().selectList(namespace + POSTFIX_SELECT_LIST_CRITERIA, criteria);
	}
		
	/**
	 * 根据Criteria 分页查询
	 * @param namespace
	 * @param criteria
	 * @return
	 */
	public Pagination getPaginationByCriteria(String namespace, Criteria criteria){
		return pageQuery(namespace + POSTFIX_SELECT_PAGINATION_CRITERIA, criteria);
	}
	
	
	public Pagination pageQuery(String sqlName, Criteria criteria){
		Integer pageNo = criteria.getPageNo();
		Integer pageSize = criteria.getPageSize();
		if(pageNo == null || pageSize == null){
			List list = getSqlSession().selectList(sqlName, criteria);
			if(list == null || list.size() == 0){
				Pagination p = new Pagination(0, 0, 0);
				p.setList(new ArrayList());
				return p;
			}else{
				return new Pagination(0, list.size(), list.size(), list);
			}
		}else{
			Assert.hasText(sqlName);
			Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
			// Count查询
			Integer totalCount = (Integer) getSqlSession().selectOne(sqlName + POSTFIX_COUNT, criteria);
			if(totalCount < 1){
				Pagination p = new Pagination(0, 0, 0);
				p.setList(new ArrayList());
				return p;
			}
			Pagination pagination = new Pagination(pageNo, pageSize, totalCount);
			// 实际查询返回分页对象
			int startIndex = pagination.getFirstResultIndex();
			criteria.setStartIndex(startIndex);
			int size = pageSize;
			criteria.setEndSize(size);
			List list = getSqlSession().selectList(sqlName, criteria);
			pagination.setList(list);
			return pagination;
		}
	}	
	
	
	/**
	 * 删除对象
	 */
/*	public int delete(String namespace, Object obj){
		return getSqlSession().delete(namespace + POSTFIX_DELETE, obj);
	}
	*/
	/**
	 * map查询.
	 * 
	 * @param map
	 *            包含各种属性的查询
	 */
/*	public <T> List<T> selectList(String namespace,  Map map){
		if(map == null){
			return this.getSqlSession().selectList(namespace + POSTFIX_SELECT_ALLLIST, null);	
		}
		else{
			map.put("findBy", "True");
			return this.getSqlSession().selectList(namespace + POSTFIX_SELECT_LIST_MAP, map);
		}
	}*/
	
	/**
	 * sql 查询.
	 * 
	 * @param sql
	 *            直接sql的语句(需要防止注入式攻击)
	 */
/*	public <T> List<T> selectList(String namespace, String sql){
		Assert.hasText(sql);
		if(StringUtils.isEmpty(sql)){
			return this.getSqlSession().selectList(namespace + POSTFIX_SELECT_ALLLIST, null);
		}			
		else{
			return this.getSqlSession().selectList(namespace + POSTFIX_SELECT_LIST_SQL, sql);
		}			
	}*/
	
		
	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的对象列表
	 */
/*	public <T> List<T> selectListBy(String namespace, String name, Object value){
		Assert.hasText(name);
		Map map = new HashMap();
		map.put(name, value);
		return selectList(namespace, map);
	}*/
	
	/**
	 * 根据属性名和属性值查询对象.
	 * 
	 * @return 符合条件的唯一对象
	 */
/*	public <T> T selectOneBy(Class<T> entityClass,String namespace,  String name, Object value){
		Assert.hasText(name);
		Map map = new HashMap();
		try{
			PropertyUtils.getProperty(entityClass.newInstance(), name);
			map.put(name, value);
			map.put("selectOneBy", "True");
			return (T) getSqlSession().selectOne(namespace + POSTFIX_SELECT_LIST_MAP, map);
		}
		catch (Exception e){
			logger.error("Error when propertie on entity," + e.getMessage(), e.getCause());
			return null;
		}		
	}*/
	
	/**
	 * 根据属性名和属性值以Like AnyWhere方式查询对象.
	 */
/*	public <T> List<T> selectListByLike(String namespace, String name, String value){
		Assert.hasText(name);
		Map map = new HashMap();
		map.put(name, value);
		map.put("selectListByLike", "True");
		return getSqlSession().selectList(namespace + POSTFIX_SELECT_LIST_MAP, map);
		
	}*/
}
